package Java7_Concurrency_Cookbook.thread_executor_framework.callable_future;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * 执行器框架(Executor Framework) 的优势之一就是, 可以运行并发任务并返回结果<br/>
 * Java并发API通过以下两个接口实现这个功能:<br/>
 * Callable, Future.<br/>
 *
 * Callable: 必须指定call()方法的返回值<br/>
 * Future: 对象主用于控制任务的状态, 以及通过call()方法来获取返回结果<br/>
 *
 * Future.get() 方法将一直等待知道Callable对象的call()方法执行完成并返回结果<br/>
 * 如果call()方法抛出了异常那么get()方法将随之抛出ExecutionException
 * @author lixiangke
 * @date 2017/11/17
 */
public class Main {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
        List<Future<Integer>> resultList = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            Integer number = random.nextInt(10);
            FactorialCalculator calculator = new FactorialCalculator(number);
            Future<Integer> result = executor.submit(calculator);
            resultList.add(result);
        }

        do {
            System.out.printf("Main: Number of Completed Tasks: %d\n", executor.getCompletedTaskCount());

            for (int i = 0; i < resultList.size(); i++) {
                Future<Integer> result = resultList.get(i);
                //System.out.printf("Main: Zoom %d : %s\n", i, result.isDone());
            }

            try {
                TimeUnit.MILLISECONDS.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } while (executor.getCompletedTaskCount() < resultList.size());

        System.out.printf("Main: Results\n");
        for (int i = 0; i < resultList.size(); i++) {
            Future<Integer> result = resultList.get(i);
            Integer number = null;
            try {
                number = result.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            System.out.printf("Main: Zoom %d: %d\n", i, number);
        }
        executor.shutdown();
    }
}
